home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
fractal
/
frasr182
/
helpcom.h
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-10
|
17KB
|
813 lines
/*
* helpcom.h
*
*
* Common #defines, structures and code for HC.C and HELP.C
*
*/
#ifndef HELPCOM_H
#define HELPCOM_H
#include "port.h"
/*
* help file signature
* If you get a syntax error, remove the LU from the end of the number.
*/
#define HELP_SIG (0xAFBC1823LU)
/*
* commands imbedded in the help text
*/
#define CMD_LITERAL 1 /* next char taken literally */
#define CMD_PARA 2 /* paragraph start code */
#define CMD_LINK 3 /* hot-link start/end code */
#define CMD_FF 4 /* force a form-feed */
#define CMD_XONLINE 5 /* exclude from online help on/off */
#define CMD_XDOC 6 /* exclude from printed document on/off */
#define CMD_CENTER 7 /* center this line */
#define CMD_SPACE 8 /* next byte is count of spaces */
#define MAX_CMD 8
/*
* on-line help dimensions
*/
#define SCREEN_WIDTH (78)
#define SCREEN_DEPTH (22)
#define SCREEN_INDENT (1)
/*
* printed document dimensions
*/
#define PAGE_WIDTH (72) /* width of printed text */
#define PAGE_INDENT (2) /* indent all text by this much */
#define TITLE_INDENT (1) /* indent titles by this much */
#define PAGE_RDEPTH (59) /* the total depth (inc. heading) */
#define PAGE_HEADING_DEPTH (3) /* depth of the heading */
#define PAGE_DEPTH (PAGE_RDEPTH-PAGE_HEADING_DEPTH) /* depth of text */
/*
* Document page-break macros. Goto to next page if this close (or closer)
* to end of page when starting a CONTENT, TOPIC, or at a BLANK line.
*/
#define CONTENT_BREAK (7) /* start of a "DocContent" entry */
#define TOPIC_BREAK (4) /* start of each topic under a DocContent entry */
#define BLANK_BREAK (2) /* a blank line */
/*
* tokens returned by find_token_length
*/
#define TOK_DONE (0) /* len == 0 */
#define TOK_SPACE (1) /* a run of spaces */
#define TOK_LINK (2) /* an entire link */
#define TOK_PARA (3) /* a CMD_PARA */
#define TOK_NL (4) /* a new-line ('\n') */
#define TOK_FF (5) /* a form-feed (CMD_FF) */
#define TOK_WORD (6) /* a word */
#define TOK_XONLINE (7) /* a CMD_XONLINE */
#define TOK_XDOC (8) /* a CMD_XDOC */
#define TOK_CENTER (9) /* a CMD_CENTER */
/*
* modes for find_token_length() and find_line_width()
*/
#define ONLINE 1
#define DOC 2
/*
* struct PD_INFO used by process_document()
*/
typedef struct
{
/* used by process_document -- look but don't touch! */
int pnum,
lnum;
/* PD_GET_TOPIC is allowed to change these */
char far *curr;
unsigned len;
/* PD_GET_CONTENT is allowed to change these */
char far *id;
char far *title;
int new_page;
/* general parameters */
char far *s;
int i;
} PD_INFO;
/*
* Commands passed to (*get_info)() and (*output)() by process_document()
*/
enum PD_COMMANDS
{
/* commands sent to pd_output */
PD_HEADING, /* call at the top of each page */
PD_FOOTING, /* called at the end of each page */
PD_PRINT, /* called to send text to the printer */
PD_PRINTN, /* called to print a char n times */
PD_PRINT_SEC, /* called to print the section title line */
PD_START_SECTION, /* called at the start of each section */
PD_START_TOPIC, /* called at the start of each topic */
PD_SET_SECTION_PAGE, /* set the current sections page number */
PD_SET_TOPIC_PAGE, /* set the current topics page number */
PD_PERIODIC, /* called just before curr is incremented to next token */
/* commands sent to pd_get_info */
PD_GET_CONTENT,
PD_GET_TOPIC,
PD_RELEASE_TOPIC,
PD_GET_LINK_PAGE
} ;
typedef int (*PD_FUNC)(int cmd, PD_INFO *pd, VOIDPTR info);
int _find_token_length(char far *curr, unsigned len, int *size, int *width);
int find_token_length(int mode, char far *curr, unsigned len, int *size, int *width);
int find_line_width(int mode, char far *curr, unsigned len);
int process_document(PD_FUNC get_info, PD_FUNC output, VOIDPTR info);
/*
* Code common to both HC.C and HELP.C (in Fractint).
* #include INCLUDE_COMMON once for each program
*/
#endif
#ifdef INCLUDE_COMMON
#ifndef XFRACT
#define getint(ptr) (*(int far *)(ptr))
#define setint(ptr,n) (*(int far *)(ptr)) = n
#else
/* Get an int from an unaligned pointer
* This routine is needed because this program uses unaligned 2 byte
* pointers all over the place.
*/
getint(ptr)
char *ptr;
{
int s;
bcopy(ptr,&s,sizeof(int));
return s;
}
/* Set an int to an unaligned pointer */
void setint(ptr, n)
int n;
char *ptr;
{
bcopy(&n,ptr,sizeof(int));
}
#endif
static int is_hyphen(char far *ptr) /* true if ptr points to a real hyphen */
{ /* checkes for "--" and " -" */
if ( *ptr != '-' )
return (0); /* that was easy! */
--ptr;
return ( *ptr!=' ' && *ptr!='-' );
}
int _find_token_length(register char far *curr, unsigned len, int *size, int *width)
{
register int _size = 0;
register int _width = 0;
int tok;
if (len == 0)
tok = TOK_DONE;
else
{
switch ( *curr )
{
case ' ': /* it's a run of spaces */
tok = TOK_SPACE;
while ( *curr == ' ' && _size < len )
{
++curr;
++_size;
++_width;
}
break;
case CMD_SPACE:
tok = TOK_SPACE;
++curr;
++_size;
_width = *curr;
++curr;
++_size;
break;
case CMD_LINK:
tok = TOK_LINK;
_size += 1+3*sizeof(int); /* skip CMD_LINK + topic_num + topic_off + page_num */
curr += 1+3*sizeof(int);
while ( *curr != CMD_LINK )
{
if ( *curr == CMD_LITERAL )
{
++curr;
++_size;
}
++curr;
++_size;
++_width;
assert(_size < len);
}
++_size; /* skip ending CMD_LINK */
break;
case CMD_PARA:
tok = TOK_PARA;
_size += 3; /* skip CMD_PARA + indent + margin */
break;
case CMD_XONLINE:
tok = TOK_XONLINE;
++_size;
break;
case CMD_XDOC:
tok = TOK_XDOC;
++_size;
break;
case CMD_CENTER:
tok = TOK_CENTER;
++_size;
break;
case '\n':
tok = TOK_NL;
++_size;
break;
case CMD_FF:
tok = TOK_FF;
++_size;
break;
default: /* it must be a word */
tok = TOK_WORD;
while (1)
{
if ( _size >= len )
break;
else if ( *curr == CMD_LITERAL )
{
curr += 2;
_size += 2;
_width += 1;
}
else if ( *curr == '\0' )
{
assert(0);
}
else if ((unsigned)*curr <= MAX_CMD || *curr == ' ' ||
*curr == '\n')
break;
else if ( *curr == '-' )
{
++curr;
++_size;
++_width;
if ( is_hyphen(curr-1) )
break;
}
else
{
++curr;
++_size;
++_width;
}
}
break;
} /* switch */
}
if (size != NULL) *size = _size;
if (width != NULL) *width = _width;
return (tok);
}
int find_token_length(int mode, char far *curr, unsigned len, int *size, int *width)
{
int tok;
int t;
int _size;
tok = _find_token_length(curr, len, &t, width);
if ( (tok == TOK_XONLINE && mode == ONLINE) ||
(tok == TOK_XDOC && mode == DOC) )
{
_size = 0;
while (1)
{
curr += t;
len -= t;
_size += t;
tok = _find_token_length(curr, len, &t, NULL);
if ( (tok == TOK_XONLINE && mode == ONLINE) ||
(tok == TOK_XDOC && mode == DOC) ||
(tok == TOK_DONE) )
break;
}
_size += t;
}
else
_size = t;
if (size != NULL )
*size = _size;
return (tok);
}
int find_line_width(int mode, char far *curr, unsigned len)
{
int size = 0,
width = 0,
lwidth = 0,
done = 0,
tok;
do
{
tok = find_token_length(mode, curr, len, &size, &width);
switch(tok)
{
case TOK_DONE:
case TOK_PARA:
case TOK_NL:
case TOK_FF:
done = 1;
break;
case TOK_XONLINE:
case TOK_XDOC:
case TOK_CENTER:
curr += size;
len -= size;
break;
default: /* TOK_SPACE, TOK_LINK or TOK_WORD */
lwidth += width;
curr += size;
len -= size;
break;
}
}
while ( !done );
return (lwidth);
}
#define DO_PRINTN(ch,n) ( pd.s = &(ch), pd.i = (n), output(PD_PRINTN, &pd, info) )
#define DO_PRINT(str,n) ( pd.s = (str), pd.i = (n), output(PD_PRINT, &pd, info) )
int process_document(PD_FUNC get_info, PD_FUNC output, VOIDPTR info)
{
int skip_blanks;
int tok;
int size,
width;
int col;
char page_text[10];
PD_INFO pd;
char nl = '\n',
sp = ' ';
int first_section,
first_topic;
pd.pnum = 1;
pd.lnum = 0;
col = 0;
output(PD_HEADING, &pd, info);
first_section = 1;
while ( get_info(PD_GET_CONTENT, &pd, info) )
{
if ( !output(PD_START_SECTION, &pd, info) )
return (0);
if ( pd.new_page && pd.lnum != 0 )
{
if ( !output(PD_FOOTING, &pd, info) )
return (0);
++pd.pnum;
pd.lnum = 0;
if ( !output(PD_HEADING, &pd, info) )
return (0);
}
else
{
if ( pd.lnum+2 > PAGE_DEPTH-CONTENT_BREAK )
{
if ( !output(PD_FOOTING, &pd, info) )
return (0);
++pd.pnum;
pd.lnum = 0;
if ( !output(PD_HEADING, &pd, info) )
return (0);
}
else if (pd.lnum > 0)
{
if ( !DO_PRINTN(nl, 2) )
return (0);
pd.lnum += 2;
}
}
if ( !output(PD_SET_SECTION_PAGE, &pd, info) )
return (0);
if ( !first_section )
{
if ( !output(PD_PRINT_SEC, &pd, info) )
return (0);
++pd.lnum;
}
col = 0;
first_topic = 1;
while ( get_info(PD_GET_TOPIC, &pd, info) )
{
if ( !output(PD_START_TOPIC, &pd, info) )
return (0);
skip_blanks = 0;
col = 0;
if ( !first_section ) /* do not skip blanks for DocContents */
{
while (pd.len > 0)
{
tok = find_token_length(DOC, pd.curr, pd.len, &size, NULL);
if (tok != TOK_XDOC && tok != TOK_XONLINE &&
tok != TOK_NL && tok != TOK_DONE )
break;
pd.curr += size;
pd.len -= size;
}
if ( first_topic && pd.len != 0 )
{
if ( !DO_PRINTN(nl, 1) )
return (0);
++pd.lnum;
}
}
if ( pd.lnum > PAGE_DEPTH-TOPIC_BREAK )
{
if ( !output(PD_FOOTING, &pd, info) )
return (0);
++pd.pnum;
pd.lnum = 0;
if ( !output(PD_HEADING, &pd, info) )
return (0);
}
else if ( !first_topic )
{
if ( !DO_PRINTN(nl, 1) )
return (0);
pd.lnum++;
}
if ( !output(PD_SET_TOPIC_PAGE, &pd, info) )
return (0);
do
{
if ( !output(PD_PERIODIC, &pd, info) )
return (0);
tok = find_token_length(DOC, pd.curr, pd.len, &size, &width);
switch ( tok )
{
case TOK_PARA:
{
int indent,
margin;
unsigned holdlen = 0;
char far *holdcurr = 0;
int in_link = 0;
++pd.curr;
indent = *pd.curr++;
margin = *pd.curr++;
pd.len -= 3;
if ( !DO_PRINTN(sp, indent) )
return (0);
col = indent;
while (1)
{
if ( !output(PD_PERIODIC, &pd, info) )
return (0);
tok = find_token_length(DOC, pd.curr, pd.len, &size, &width);
if ( tok == TOK_NL || tok == TOK_FF )
break;
if ( tok == TOK_DONE )
{
if (in_link == 0)
{
col = 0;
++pd.lnum;
if ( !DO_PRINTN(nl, 1) )
return (0);
break;
}
else if (in_link == 1)
{
tok = TOK_SPACE;
width = 1;
size = 0;
++in_link;
}
else if (in_link == 2)
{
tok = TOK_WORD;
width = strlen(page_text);
col += 8 - width;
size = 0;
pd.curr = page_text;
++in_link;
}
else if (in_link == 3)
{
pd.curr = holdcurr;
pd.len = holdlen;
in_link = 0;
continue;
}
}
if ( tok == TOK_PARA )
{
col = 0; /* fake a nl */
++pd.lnum;
if ( !DO_PRINTN(nl, 1) )
return (0);
break;
}
if (tok == TOK_XONLINE || tok == TOK_XDOC )
{
pd.curr += size;
pd.len -= size;
continue;
}
if ( tok == TOK_LINK )
{
pd.s = pd.curr+1;
if ( get_info(PD_GET_LINK_PAGE, &pd, info) )
{
in_link = 1;
sprintf(page_text, "(p. %d)", pd.i);
}
else
in_link = 3;
holdcurr = pd.curr + size;
holdlen = pd.len - size;
pd.len = size - 2 - 3*sizeof(int);
pd.curr += 1 + 3*sizeof(int);
continue;
}
/* now tok is TOK_SPACE or TOK_WORD */
if (col+width > PAGE_WIDTH)
{ /* go to next line... */
if ( !DO_PRINTN(nl, 1) )
return (0);
if ( ++pd.lnum >= PAGE_DEPTH )
{
if ( !output(PD_FOOTING, &pd, info) )
return (0);
++pd.pnum;
pd.lnum = 0;
if ( !output(PD_HEADING, &pd, info) )
return (0);
}
if ( tok == TOK_SPACE )
width = 0; /* skip spaces at start of a line */
if ( !DO_PRINTN(sp, margin) )
return (0);
col = margin;
}
if (width > 0)
{
if (tok == TOK_SPACE)
{
if ( !DO_PRINTN(sp, width) )
return (0);
}
else
{
if ( !DO_PRINT(pd.curr, (size==0) ? width : size) )
return (0);
}
}
col += width;
pd.curr += size;
pd.len -= size;
}
skip_blanks = 0;
width = size = 0;
break;
}
case TOK_NL:
if (skip_blanks && col == 0)
break;
++pd.lnum;
if ( pd.lnum >= PAGE_DEPTH || (col == 0 && pd.lnum >= PAGE_DEPTH-BLANK_BREAK) )
{
if ( col != 0 ) /* if last wasn't a blank line... */
{
if ( !DO_PRINTN(nl, 1) )
return (0);
}
if ( !output(PD_FOOTING, &pd, info) )
return (0);
++pd.pnum;
pd.lnum = 0;
skip_blanks = 1;
if ( !output(PD_HEADING, &pd, info) )
return (0);
}
else
{
if ( !DO_PRINTN(nl, 1) )
return (0);
}
col = 0;
break;
case TOK_FF:
if (skip_blanks)
break;
if ( !output(PD_FOOTING, &pd, info) )
return (0);
col = 0;
pd.lnum = 0;
++pd.pnum;
if ( !output(PD_HEADING, &pd, info) )
return (0);
break;
case TOK_CENTER:
width = (PAGE_WIDTH - find_line_width(DOC,pd.curr,pd.len)) / 2;
if ( !DO_PRINTN(sp, width) )
return (0);
break;
case TOK_LINK:
skip_blanks = 0;
if ( !DO_PRINT(pd.curr+1+3*sizeof(int),
size-3*sizeof(int)-2) )
return (0);
pd.s = pd.curr+1;
if ( get_info(PD_GET_LINK_PAGE, &pd, info) )
{
width += 9;
sprintf(page_text, " (p. %d)", pd.i);
if ( !DO_PRINT(page_text, strlen(page_text)) )
return (0);
}
break;
case TOK_WORD:
skip_blanks = 0;
if ( !DO_PRINT(pd.curr, size) )
return (0);
break;
case TOK_SPACE:
skip_blanks = 0;
if ( !DO_PRINTN(sp, width) )
return (0);
break;
case TOK_DONE:
case TOK_XONLINE: /* skip */
case TOK_XDOC: /* ignore */
break;
} /* switch */
pd.curr += size;
pd.len -= size;
col += width;
}
while (pd.len > 0);
get_info(PD_RELEASE_TOPIC, &pd, info);
first_topic = 0;
} /* while */
first_section = 0;
} /* while */
if ( !output(PD_FOOTING, &pd, info) )
return (0);
return (1);
}
#undef DO_PRINT
#undef DO_PRINTN
#undef INCLUDE_COMMON
#endif /* #ifdef INCLUDE_COMMON */